package com.zhangsun.service.impl;

import cn.hutool.log.StaticLog;
import com.zhangsun.dto.QuartzDto;
import com.zhangsun.service.QuartzJobService;
import com.zhangsun.vo.QuartzEditVo;
import com.zhangsun.vo.QuartzVo;
import org.quartz.*;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Service
public class QuartzJobServiceImpl implements QuartzJobService {

    @Autowired
    private Scheduler scheduler;

    @Override
    public List<QuartzDto> findAll() {
        GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
        List<QuartzDto> jobList = new ArrayList<>();

        try {
            Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
            for (JobKey jobKey : jobKeys) {
                List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
                for (Trigger trigger : triggers) {
                    QuartzDto job = new QuartzDto();
                    job.setJobClassName(jobKey.getName());
                    job.setJobGroupName(jobKey.getGroup());

                    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
                    job.setJobStatus(triggerState.name());
                    if (trigger instanceof CronTrigger) {
                        CronTrigger cronTrigger = (CronTrigger) trigger;
                        String cronExpression = cronTrigger.getCronExpression();
                        job.setCronExpression(cronExpression);
                    }
                    jobList.add(job);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return jobList;
    }

    @Override
    public void create(QuartzEditVo vo) {
        try {
            // 启动调度器
            scheduler.start();

            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(vo.getJobClassName()).getClass()).withIdentity(vo.getJobClassName(), vo.getJobGroupName()).build();

            //表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(vo.getCronExpression());

            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(vo.getJobClassName(), vo.getJobGroupName())
                    .withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (Exception e) {
            StaticLog.error(e);
        }
    }

    @Override
    public void update(QuartzEditVo vo) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(vo.getJobClassName(), vo.getJobGroupName());
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(vo.getCronExpression());

            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();

            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
        } catch (Exception e) {
            StaticLog.error(e);
        }
    }

    @Override
    public void pause(QuartzVo vo) {
        try {
            scheduler.pauseJob(JobKey.jobKey(vo.getJobClassName(), vo.getJobGroupName()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void resume(QuartzVo vo) {
        try {
            scheduler.resumeJob(JobKey.jobKey(vo.getJobClassName(), vo.getJobGroupName()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void delete(QuartzVo vo) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(vo.getJobClassName(), vo.getJobGroupName()));
            scheduler.unscheduleJob(TriggerKey.triggerKey(vo.getJobClassName(), vo.getJobGroupName()));
            scheduler.deleteJob(JobKey.jobKey(vo.getJobClassName(), vo.getJobGroupName()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }
}
